import java.lang.reflect.*;
import java.io.*;
import java.util.*;

public class LCExec {

	public static void main(String[] args) {
		if (args.length < 1) {
			System.out.println("need class filename and methodName to execute !");
			return;
		}

		System.out.print("args : ");
		for(int i=0; i< args.length; i++) {
			System.out.print(args[i]+" ");
		}
		System.out.println();

		String[] fm = args[0].split("\\.");
		if(fm.length!=2){
			System.out.println("argument format is {filename}.{method} !");
			return;
		}

		List<Class<?>> argumentClass = new ArrayList<>();
		List<Object> argumentValue = new ArrayList<>();
		int argumentNum = (args.length-1)/2;
		for(int i=0; i<argumentNum; i++) {
			int n = i *2 +1;
			if("intarray".equals(args[n])){
				String[] argStr = args[n+1].split(",");
				int[] argInt = new int[argStr.length]; 
				for(int j=0; j<argStr.length;j++){
					argInt[j] = Integer.valueOf(argStr[j]);
				}
				argumentClass.add(int[].class);
				argumentValue.add(argInt);
			}else if ("int".equals(args[n])){
				argumentClass.add(int.class);
				argumentValue.add(Integer.valueOf(args[n+1]));
			}else if ("stringarray".equals(args[n])){
				String[] argStr = args[n+1].split(",");
				argumentClass.add(String[].class);
				argumentValue.add(argStr);
			}else if ("string".equals(args[n])){
				argumentClass.add(String.class);
				argumentValue.add(args[n+1]);
			}else if ("chararray".equals(args[n])){
				String[] argStr = args[n+1].split(",");
				char[] argChar = new char[argStr.length]; 
				for(int j=0; j<argStr.length;j++){
					argChar[j] = argStr[j].charAt(0);
				}
				argumentClass.add(char[].class);
				argumentValue.add(argChar);
			}else if ("char".equals(args[n])){
				argumentClass.add(char.class);
				argumentValue.add(args[n+1].charAt(0));
			}else if (args[n].startsWith("intarray")){
				String[] argStr = args[n].split(":");
				int len = argStr.length - 1;
				if(len>3) {
					System.out.println("argument format is supported ! Max supports up to 3-bit arrays !");
					return;
				}
				String[] argIntStr = args[n+1].split(",");
				if(len==1){
					int length = Integer.valueOf(argStr[1]);
					if(argIntStr.length != length){
						System.out.println("Array parameters are inconsistent !");
						return;
					}
					int[] argInt = new int[length]; 
					for(int j=0; j<length;j++){
						argInt[j] = Integer.valueOf(argIntStr[j]);
					}
					argumentClass.add(int[].class);
					argumentValue.add(argInt);
				}else if(len==2){
					int length = Integer.valueOf(argStr[1]);
					int length2 = Integer.valueOf(argStr[2]);
					if(argIntStr.length != length*length2){
						System.out.println("Array parameters are inconsistent !");
						return;
					}
					int[][] argInt = new int[length][length2];
					for(int j=0; j<length;j++){
						for(int m=0;m<length2;m++)
							argInt[j][m] = Integer.valueOf(argIntStr[j*length2 +m]);
					}
					argumentClass.add(int[][].class);
					argumentValue.add(argInt);
				}else{
					int length = Integer.valueOf(argStr[1]);
					int length2 = Integer.valueOf(argStr[2]);
					int length3 = Integer.valueOf(argStr[3]);
					if(argIntStr.length != length*length2*length3){
						System.out.println("Array parameters are inconsistent !");
						return;
					}
					int[][][] argInt = new int[length][length2][length3];
					for(int j=0; j<length;j++){
						for(int m=0;m<length2;m++){
							for(int mm=0;mm<length3;mm++)
								argInt[j][m][mm] = Integer.valueOf(argIntStr[j*length2+m*length3+mm]);
						}
					}
					argumentClass.add(int[][][].class);
					argumentValue.add(argInt);
				}
			} else {
				System.out.println("argument format is not supported !");
				return;
			}
		}

		try {
			
			LeetcodeClassLoader classLoader = new LeetcodeClassLoader(Thread.currentThread().getContextClassLoader());

			String classname = fm[0];
			if(!classname.toLowerCase().startsWith("leetcode")){
				classname = "Leetcode"+fm[0];
			}
			Class<?> clazz = classLoader.loadClass(classname);
			if (clazz == null) {
				System.out.println(fm[0] +" : class filename is not found !");
				return;
			}

			Method method = null;
			if(argumentClass.isEmpty()){
				method = clazz.getMethod(fm[1]);
			}else{
				Class<?>[] argumentClassArr = new Class<?>[argumentClass.size()];
				argumentClass.toArray(argumentClassArr);
				method = clazz.getMethod(fm[1], argumentClassArr);
			}
			if (method == null) {
				System.out.println(fm[1] + " : methodName is not found !");
				return;
			}

			Object obj;
			if(argumentValue.isEmpty())
				obj = method.invoke(clazz.newInstance());
			else
				obj = method.invoke(clazz.newInstance(), argumentValue.toArray());
			
			System.out.println("result is "+ obj);
		} catch (ClassNotFoundException ex) {
			System.out.println("class filename is not found !");
		} catch (NoSuchMethodException ex) {
			System.out.println("methodName is not found !");
		} catch (InstantiationException ex) {
			System.out.println("class need Argumentless constructor !");
		} catch (IllegalAccessException ex) {
			System.out.println("call method error !");
		} catch (InvocationTargetException ex) {
			System.out.println("call method error !");
		}
	}
}

class LeetcodeClassLoader extends ClassLoader {
	private final String fileExtension = ".class";
	private String classpath;
	
	public LeetcodeClassLoader(ClassLoader parent) {
        super(parent);
        this.classpath = System.getProperty("user.dir");
        System.out.println("classpath is "+this.classpath);
    }

    private byte[] loadClassDate(String name) {
        InputStream is = null;
        byte[] data = null;
        ByteArrayOutputStream baos = null;

        try {
            is = new FileInputStream(this.classpath + name.replace(".", "/") + this.fileExtension);
            baos = new ByteArrayOutputStream();
            int ch = 0;
            while (-1 != (ch = is.read())) {
                baos.write(ch);
            }
            data = baos.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            try {
                if (baos != null) {
                    baos.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return data;
    }
}